home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / include / Pool.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  8.3 KB  |  337 lines

  1. #ifndef _POOL_C_
  2. #define _POOL_C_
  3. /*
  4.  *   $RCSfile: Pool.c,v $  
  5.  *   $Revision: 1.1.1.1 $  
  6.  *   $Date: 1996/05/04 21:55:09 $      
  7.  */ 
  8. /**********************************************************************
  9. * EXODUS Database Toolkit Software
  10. * Copyright (c) 1991 Computer Sciences Department, University of
  11. *                    Wisconsin -- Madison
  12. * All Rights Reserved.
  13. *
  14. * Permission to use, copy, modify and distribute this software and its
  15. * documentation is hereby granted, provided that both the copyright
  16. * notice and this permission notice appear in all copies of the
  17. * software, derivative works or modified versions, and any portions
  18. * thereof, and that both notices appear in supporting documentation.
  19. *
  20. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  21. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  22. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  23. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  24. *
  25. * The EXODUS Project Group requests users of this software to return 
  26. * any improvements or extensions that they make to:
  27. *
  28. *   EXODUS Project Group 
  29. *     c/o David J. DeWitt and Michael J. Carey
  30. *   Computer Sciences Department
  31. *   University of Wisconsin -- Madison
  32. *   Madison, WI 53706
  33. *
  34. *     or exodus@cs.wisc.edu
  35. *
  36. * In addition, the EXODUS Project Group requests that users grant the 
  37. * Computer Sciences Department rights to redistribute these changes.
  38. **********************************************************************/
  39.  
  40.  
  41. #ifndef  __GNUC__
  42. #include "sysdefs.h"
  43. #include "checking.h"
  44. #include "ess.h"
  45. #include "list.h"
  46. #include "Pool.h"
  47. #include "trace.h"
  48. #include "error.h"
  49. #endif  __GNUC__
  50.  
  51. template <class CONTENTS>
  52. void
  53. Pool<CONTENTS>:: listMake( 
  54.     LIST *list,        /* already initialized, list of elements to create */
  55.     LIST *mallocList,    /* already initialized, list of malloc-ed areas */
  56.     int    howMany
  57. )
  58. {
  59.     register int i;
  60.     register char *c;
  61.     CONTENTS    *contents;
  62.     LISTELEMENT    *element;
  63.     int        numbytes = sizeof(LISTELEMENT) + (howMany * elementSize);
  64.  
  65.     /* First: malloc space for one LISTELEMENT (to point to the
  66.      * malloced space to be freed), and for all the LISTELEMENTS
  67.      * and CONTENTS structures needed for the pool.
  68.      */
  69.  
  70.     c = (char *) malloc( numbytes );
  71.     if(c == NULL) {
  72.         SM_ERROR(TYPE_FATAL, esmMALLOCFAILED);
  73.     }
  74.     TRPRINT(TR_BF, TR_LEVEL_1, ("malloced area 0x%x",c));
  75.     nmallocs++;
  76.     spaceRequirement  += numbytes;
  77.     bzero(c, numbytes);
  78.  
  79.     /* 
  80.      * Put on the mallocList: 
  81.      * one LISTELEMENT pointing to this free-able segment
  82.      */
  83.     element = (LISTELEMENT *)c;
  84.     initializeListElement(element, c);
  85.     listEnq(mallocList, element);
  86.     c += sizeof(LISTELEMENT);
  87.  
  88.  
  89.     /* Now create a pool of CONTENTS, linked through their LISTELEMENTS
  90.      * (each CONTENTS type must contain a list, which we find by the
  91.      * listlocation() member function of the parameter class)
  92.      */
  93.     for (contents = (CONTENTS *)c,i = 0;   i < howMany;   i++) {
  94.         contents->Init();
  95.         element = contents->listlocation(this->unique);
  96.  
  97.         /* contents->Init() should have initialized ALL list elements,
  98.          * so we do not need to do this:
  99.          *    initializeListElement( element, (char *)contents );
  100.          */
  101.         listEnq(list,  element);
  102.         contents++; 
  103.     }
  104.     totalQty += howMany;
  105. }    /* listMake */
  106.  
  107. template <class CONTENTS>
  108. Pool<CONTENTS>::Pool (
  109.     char            *name,
  110.     int                which,
  111.     int                howMany, 
  112.     FLAGS            flags
  113. )
  114. {
  115.     TRPRINT(TR_BF, TR_LEVEL_1, ("new pool :%s", name));
  116.  
  117.     initializeList( &this->freeList );
  118.     initializeList( &this->mallocedList );
  119.  
  120.     (void) bzero(this->name, sizeof(this->name));
  121.     {     int length;
  122.         length = strlen(name);
  123.         if(length >= sizeof(this->name))
  124.             length = sizeof(this->name)-1;
  125.  
  126.         (void) strncpy(this->name, name, length);
  127.     }
  128.  
  129.     this->unique = which;
  130.  
  131.     this->maxUsed = this->currentUsed = 0;
  132.     this->totalQty = 0;
  133.  
  134.     this->elementSize = sizeof(CONTENTS);
  135.     this->spaceRequirement = this->nmallocs = 0;
  136.     this->flags = flags;
  137.     this->lastMallocedQty = howMany;
  138.  
  139.     listMake(&this->freeList, &this->mallocedList, howMany);
  140. } /* constructor */
  141.  
  142. template <class CONTENTS>
  143. Pool<CONTENTS>::~Pool () 
  144. {
  145.     register char    *freeableArea;
  146.  
  147.     /* dispose of all malloc-ed areas  */
  148.  
  149.     TRPRINT(TR_BF, TR_LEVEL_1, ("~Pool %s", this->name ));
  150.     if(LIST_EMPTY( &(this->mallocedList) ) )
  151.         return;
  152.  
  153.     while ((freeableArea = 
  154.         (char *) listDeq( &(this->mallocedList) )) != NULL)    {
  155.         free((char *)freeableArea);
  156.     }
  157.     TRPRINT(TR_BF, TR_LEVEL_1, ("End ~Pool %s", this->name ));
  158. } /* destructor */
  159.  
  160. template <class CONTENTS>
  161. CONTENTS *
  162. Pool<CONTENTS>::Get()
  163. {
  164.     register CONTENTS    *contents;
  165.  
  166.     TRPRINT(TR_BF, TR_LEVEL_1, ("Get from :%s", this->name));
  167.  
  168.     CHECK_LIST_MAGIC(&freeList);
  169.  
  170.     if (LIST_EMPTY( &freeList) )    {
  171.  
  172.         if (flags & POOL_NOMORE_GETMORE )    {
  173.             /* try to get again as much */
  174.             /* later, we might want to try different amounts */
  175.             listMake(&this->freeList, &this->mallocedList, this->lastMallocedQty);
  176.         } else {
  177.             if (flags & POOL_NOMORE_ISFATAL )    {
  178.                 SM_ERROR(TYPE_FATAL, esmPOOLEMPTY);
  179.             } else if (flags & POOL_NOMORE_ISERROR )    {
  180.                 SM_ERROR(TYPE_LOG, esmPOOLEMPTY);
  181.             } 
  182.             return(NULL);
  183.         }
  184.     } 
  185.     if ((contents = (CONTENTS *) listDeq( &(freeList) )) == NULL)    {
  186.         SM_ERROR(TYPE_FATAL, esmINTERNAL);
  187.     }
  188.     currentUsed++;
  189.  
  190.     if (currentUsed > maxUsed)    {
  191.         maxUsed = currentUsed;
  192.     }
  193.  
  194.     TRPRINT(TR_BF, TR_LEVEL_2, ("contents:%x", contents));
  195.  
  196.     contents->ReInit();
  197.  
  198.     return( contents );
  199. }
  200.  
  201. template <class CONTENTS>
  202.  void
  203. Pool<CONTENTS>::ForEach(    
  204.     int                nargs, /* TOTAL # args, including func */
  205. #ifndef __GNUC__
  206.     FOREACHFUNC foreachfunc,
  207. #endif __GNUC__
  208.     ...
  209. )
  210. {
  211.     va_list         ap;
  212. #define MAXNARGS     10
  213.     void            *arglist[MAXNARGS];
  214.     LISTELEMENT     *listelement ;
  215.     LISTELEMENT     *next ;
  216. #ifdef __GNUC__
  217.     FOREACHFUNC foreachfunc;
  218. #endif __GNUC__
  219.  
  220.     TRPRINT(TR_BF, TR_LEVEL_1, ("ForEach :%s", this->name));
  221. #ifdef __GNUC__
  222.     SM_ASSERT(LEVEL_1, (nargs <= MAXNARGS));
  223. #endif __GNUC__
  224.  
  225.     SM_ASSERT(LEVEL_1, (nargs >= 1)); /* must include func */
  226.     {
  227.         register int i;
  228.  
  229. #ifdef __GNUC__
  230.         va_start(ap,nargs);    
  231.         foreachfunc = va_arg(ap,FOREACHFUNC);
  232. #else
  233.         va_start(ap,foreachfunc);    
  234. #endif __GNUC__
  235.  
  236.         for(i=0; i<nargs; i++) {
  237.             arglist[i] = va_arg(ap,void *);
  238.             TRPRINT(TR_BF, TR_LEVEL_1, 
  239.                 ("arglist[%d]=0x%x", i, arglist[i]));
  240.         }
  241.         va_end(ap);
  242.     }
  243.  
  244.     for( listelement = FIRST_LIST_ELEMENT_ITSELF( &(freeList) );
  245.         listelement != &(freeList); listelement = next) {
  246.  
  247.         /* Get the next list element before calling the function.
  248.          * That way, if the function removes the list element from
  249.          * the list, we can still function properly.
  250.          * We will not catch new elements, should the function
  251.          * cause new elements to be added to the list.
  252.          */
  253.         next = NEXT_LIST_ELEMENT_ITSELF( listelement );
  254.         if((*foreachfunc)(listelement->item, 
  255.             arglist[0], arglist[1], arglist[2], arglist[3],
  256.             arglist[4], arglist[5], arglist[6], arglist[7],
  257.             arglist[8], arglist[9]))
  258.             return;
  259.     }
  260. }
  261.  
  262. template <class CONTENTS>
  263.  void
  264. Pool<CONTENTS>::Put(    /* counterpart to listEnq */
  265.     CONTENTS *contents
  266. )
  267. {
  268.     register LISTELEMENT    *element = contents->listlocation(this->unique);
  269.  
  270.     TRPRINT(TR_BF, TR_LEVEL_1, ("Put Pool:%s element:%x", name, element));
  271.  
  272.     CHECK_LIST_MAGIC( &freeList );
  273.     INIT_LIST_MAGIC(element); 
  274.  
  275.     /* ERROR if element is in a list already */
  276.     listEnq( &freeList, element );
  277.  
  278.     currentUsed--;
  279. }
  280.  
  281. template <class CONTENTS>
  282.  void
  283. Pool<CONTENTS>::Move(    /* counterpart to listMoveEnq */
  284.     CONTENTS *contents
  285. )
  286. {
  287.     register LISTELEMENT    *element  = contents->listlocation(this->unique);
  288.     TRPRINT(TR_BF, TR_LEVEL_1, ("Pool:%s element:%x", name, element));
  289.  
  290.     CHECK_LIST_MAGIC(&freeList);
  291.     INIT_LIST_MAGIC(element); 
  292.  
  293.     /* ERROR if element is NOT in a list already */
  294.     listMoveEnq( &freeList, element );
  295.  
  296.     currentUsed--;
  297. }
  298.  
  299. template <class CONTENTS>
  300. void    
  301. Pool<CONTENTS>::Stats( FILE *f )
  302. #ifdef DEBUG
  303.     /*
  304.      *    these ifdefs look funny because g++ (2.3.1) has a bug
  305.      *    in adding line directive to template functions.
  306.      */
  307. {
  308. #else
  309. {
  310. #endif DEBUG
  311.     fprintf(f, "Pool %s: %d malloc%s for %d elements\n",
  312.         name, nmallocs, nmallocs==1?"":"s", totalQty);
  313.     fprintf(f, "\t usage: highwater=%d, in use now=%d\n",
  314.         maxUsed, currentUsed);
  315.  
  316. #ifndef DEBUG
  317. }
  318. #else
  319.     {
  320.         int i=0;
  321.         register LISTELEMENT *listelement;
  322.  
  323.         if(LIST_EMPTY( &(this->mallocedList)) )
  324.             return;
  325.  
  326.         listelement = FIRST_LIST_ELEMENT_ITSELF( &(this->mallocedList) );
  327.         while (listelement  != &(this->mallocedList) ) {
  328.             i++;
  329.             /* fprintf(stderr, "malloced area 0x%x\n", listelement->item); */
  330.             listelement = NEXT_LIST_ELEMENT_ITSELF( listelement);
  331.         }
  332.         /* fprintf(stderr, "total areas %d\n", i); */
  333.     }
  334. }
  335. #endif DEBUG
  336. #endif /* _POOL_C_ */
  337.